'''
题目描述：使用栈实现队列的下列操作：
push (x) -- 将一个元素放入队列的尾部；
pop () -- 从队列首部移除元素；
peek () -- 返回队列首部的元素(但是不移除它)
empty () -- 返回队列是否为空

资料补充：
使用两个栈（输入栈和输出栈）模拟队列时，需要注意以下关键要点，以确保队列的先进先出（FIFO）特性正确实现：
1. 元素转移的时机
仅当输出栈为空时，才将输入栈的所有元素转移到输出栈。
转移时要一次性将输入栈的所有元素全部转移，不能只转移部分。
2. 元素转移的顺序
输入栈的元素弹出后直接压入输出栈，利用栈的 "后进先出" 特性，自然实现元素顺序反转。
例如：输入栈 [1,2,3] 转移后，输出栈变为 [3,2,1]，弹出时会按 1,2,3 顺序返回，符合队列特性。
3. 操作的原子性
对于 pop() 和 peek() 操作，必须先完成元素转移（如果需要），再执行后续操作。
不允许在转移过程中插入新元素，确保队列操作的完整性。
4. 边界情况处理
当两个栈都为空时，pop() 操作应考虑是否抛出异常（根据需求设计）。
empty() 方法必须同时检查两个栈是否都为空，仅当两者都为空时才返回 True。
5. 避免重复转移
输出栈非空时，直接操作输出栈即可，无需处理输入栈，避免重复转移导致顺序混乱。
例如：输出栈还有元素时，pop() 直接取输出栈顶，不需要查看输入栈。
总结：
核心原则是通过 "输入栈存、输出栈取" 的模式，利用两次栈操作（入栈 + 出栈）实现元素顺序反转，从而模拟队列的 FIFO 特性。关键在于严格控制元素从输入栈到输出栈的转移时机和方式，确保任何时候操作的都是 "最早进入队列" 的元素。
从数据结构设计的角度，"用栈来模拟队列" 的目标是复现队列的核心行为(上述4个)，而非 100% 复刻队列的所有可能的操作。
列表的 append()（添加到末尾）和 pop()（从末尾移除）是一对对称操作，共同实现了栈的 “后进先出”（LIFO）特性：

'''

class MyQueue:

    def __init__(self):
        #初始化两个栈，一个用于输入，一个用于输出
        self.in_stack = []   # 输入栈，用于接收新元素
        self.out_stack = []  # 输出栈，用于提供队列操作

    def push(self, x: int) -> None:
        #将元素x加入队列尾部  push只涉及输入栈
        self.in_stack.append(x)  #直接将元素压入输入栈

    def pop(self) -> int:
        #移除并返回队列首部的元素
        # 如果输出栈为空，将输入栈的所有元素(while体现了)转移到输出栈
        #仅当输出栈为空时，才将输入栈的所有元素转移到输出栈。
        #转移时要一次性将输入栈的所有元素全部转移，不能只转移部分。
        #输入栈的元素弹出后直接压入输出栈，利用栈的 "后进先出" 特性，自然实现元素顺序反转。
        if not self.out_stack:
            #输出栈没有数据了不代表输入栈也没有数据，所以还需要再来看看输入栈
            while self.in_stack:
                #注意，最后是list(self.in_stack)的pop()方法，不要看错
                self.out_stack.append(self.in_stack.pop())
        #对于 pop() 和 peek() 操作，必须先完成全部元素的转移（如果需要的话），再执行后续操作。
        #不允许在转移过程中插入新元素，确保队列操作的完整性。
        # 弹出输出栈的栈顶元素（即队列的首部元素）
        return self.out_stack.pop()

    def peek(self) -> int:
        #返回队列首部的元素 逻辑与pop类似，但不弹出元素
        if not self.out_stack:
            while self.in_stack:
                self.out_stack.append(self.in_stack.pop())
        # 返回输出栈的栈顶元素
        #list.pop(-1)等价于list.pop()（pop方法不带参数时，pop() 默认删除并返回最后一个元素）
        #下面只是"查看"out_statck的最后一个元素，并没有移除最后一个元素 本方法是peek方法，不是pop方法
        return self.out_stack[-1]

    def empty(self) -> bool:
        #判断队列是否为空 当两个栈都为空时，队列才可以说是空
        return not self.in_stack and not self.out_stack

# 测试示例
obj = MyQueue()
obj.push(1)
print(obj.peek())  #
print(obj.pop())   #
print(obj.empty()) #
obj.push(2)
print(obj.peek())  #
print(obj.pop())   #
print(obj.empty()) #
obj.push(3)
obj.push(4)
print(obj.peek())  #
print(obj.pop())   #
print(obj.empty()) #



print("--------------")
list1  = [1,2,3]
print(list1[-1])#3
print(list1.pop(-1)) #3
print(list1.pop()) #2
print(list1[-1])#1